#pragma once
#include "socket.hpp"
#include "Log.hpp"
#include "connection.hpp"
#include "epoller.hpp"
#include <sys/epoll.h>
#include <memory>
#include <cstring>
#include <cerrno>
#include <unordered_map>
#include <vector>
using namespace SocketModule;
using namespace LogModule;
using namespace epoll_module;
using connection_t = std::shared_ptr<connection>;
class reactor
{
    const static int event_num = 64;

public:
    reactor()
        : _epoller(std::make_unique<epoller>()), _is_running(false)
    {
    }

    void init()
    {
        _epoller->init();
        _events.reserve(event_num);
    }

    bool IsConnectionExists(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }

    void insert_connection(connection &conn)
    {
        if (IsConnectionExists(conn.fd()))
        {
            LOG(LogLevel::ERROR) << "connection already exists";
            return;
        }
        _connections[conn.fd()] = std::make_shared<connection>(conn);
        _epoller->add(conn.fd(), conn.events());
    }

    void del_connection(int fd)
    {
        if(!IsConnectionExists(fd))
        {
            LOG(LogLevel::ERROR) << "connection does not exist";
            return;
        }
        // 1. 从内核中移除对sockfd的关心
        _epoller->del(fd);
        // 2. 关闭特定的文件描述
        _connections[fd]->close();
        // 3. 从_connections中移除对应的connection
        _connections.erase(fd);


    }
    void enable_read_write(int fd, bool read, bool write)
    {
        if(!IsConnectionExists(fd))
        {
            LOG(LogLevel::ERROR) << "connection does not exist";
            return;
        }
        uint32_t events = EPOLLIN & read | EPOLLOUT & write | EPOLLET;
        //写入connection中
        _connections[fd]->set_events(events);
        //更新epoll事件
        _epoller->ctl(fd, events, EPOLL_CTL_MOD);
    }


    void dispatcher(int n)
    {
        for (int i = 0; i < n; ++i)
        {
            int sock_fd = _events[i].data.fd;
            uint32_t events = _events[i].events;
            if ((events & EPOLLERR) || (events & EPOLLHUP))
            {
                events = (EPOLLIN | EPOLLOUT);
            }
            if (IsConnectionExists(sock_fd))
            {
                if (events & EPOLLIN)
                {
                    _connections[sock_fd]->receiver();
                }
                if (events & EPOLLOUT)
                {
                    _connections[sock_fd]->sender();
                }
            }
        }
    }


    void loop_once()
    {
        int n = _epoller->wait(_events.data(), _events.capacity());
        dispatcher(n);
    }


    void loop()
    {
        _is_running = true;
        while (_is_running)
        {
            loop_once();
        }
        _is_running = false;
    }

    void stop()
    {
        _is_running = false;
    }

private:
    // 只关心一个个的connection
    // epoll_server只负责把各connection的fd交给epoll管理和派发任务
    // connection负责管理自己的fd，该fd的读写
    std::unordered_map<int, connection_t> _connections;
    std::unique_ptr<epoller> _epoller;
    std::vector<epoll_event> _events;
    bool _is_running;
};